using Framework.Core;
using System;
using System.Collections.Generic;

namespace Framework
{
    public class HttpManager
    {
        private Queue<HttpRequestTask> _requestList = new Queue<HttpRequestTask>();
        private List<HttpRequestAgent> _sendList = new List<HttpRequestAgent>();
        private List<HttpRequestTask> _completeList = new List<HttpRequestTask>();
        private Dictionary<int, HttpRequestTask> _requestToTask = new Dictionary<int, HttpRequestTask>();
        protected ICoroutineManager coroutineManager;
        protected int sendInstanceCount;
        public HttpManager()
        {
            sendInstanceCount = 50;
        }
        public void SetCoroutineManager(ICoroutineManager value)
        {
            coroutineManager = value;
        }
        public void SetSendCount(int count = 50)
        {
            if (count < 1)
            {
                count = 1;
            }
            if (count > 100)
            {
                count = 100;
            }
            sendInstanceCount = count;
        }
        public void Update(float deltaTime, float unscaledDeltaTime)
        {
            int count;
            count = _completeList.Count;
            while (count-- > 0)
            {
                var task = _completeList[count];
                task.Tick();
                if (task.Finished)
                {
                    _completeList.RemoveAt(count);
                    if (task.Callback != null)
                    {
                        task.Callback.Invoke(task.Result);
                    }
                    ReferencePool.Release(task);
                }
            }
            count = _sendList.Count;
            while (count-- > 0)
            {
                var http = _sendList[count];
                if (http.Finished)
                {
                    _sendList.RemoveAt(count);
                    HttpRequestTask task;
                    if (_requestToTask.TryGetValue(http.Id, out task))
                    {
                        _requestToTask.Remove(http.Id);
                        _completeList.Add(task);
                    }
                    ReferencePool.Release(http);
                }
            }
            var sendCount = _sendList.Count;
            count = _requestList.Count;
            if (count > 0)
            {
                while (count-- > 0)
                {
                    if (sendCount >= this.sendInstanceCount)
                    {
                        break;
                    }
                    var task = _requestList.Dequeue();
                    var request = GetRequestAgent();
                    var id = request.Send(task);
                    _requestToTask.Add(id, task);
                    _sendList.Add(request);
                }
            }
        }
        public HttpRequestTask Request(string url)
        {
            var task = GetTask();
            task.Set(url);
            if (task.ID > 0)
            {
                _requestList.Enqueue(task);
            }
            return task;
        }
        public HttpRequestTask Request(string url, Action<HttpResult> callback)
        {
            var task = Request(url);
            if (task.ID > 0)
            {
                task.Set(callback);
            }
            return task;
        }
        protected virtual HttpRequestTask GetTask()
        {
            var task = ReferencePool.Get<HttpRequestTask>();
            return task;
        }
        protected virtual HttpRequestAgent GetRequestAgent()
        {
            var request = ReferencePool.Get<UnityHttpRequest>();
            request.SetCoroutineManager(this.coroutineManager);
            return request;
        }
    }
}